#include "ULCore_Algorithm.h"

//ULC_ACData
void ULC_ACData::Init()
{
	ac = dtDiff = 0;
	memset(redBalls, 0, sizeof(int) * UL_RED_BALLS_COUNT);
	memset(dtDataFinal, -1, sizeof(int) * DT_DATA_MAX_SIZE);
	memset(dtDataOut, -1, sizeof(int) * DT_DATA_MAX_SIZE);
}

ULC_ACData::ULC_ACData()
{
	Init();
}

ULC_ACData::ULC_ACData(ULC_Balls *balls)
{
	Caculate(balls);
}

static bool NumberExisted(int *arr, int index, int data)
{
	for (int i = 0; i <= index; i++){
		if (data == arr[i]){
			return true;
		}
	}

	return false;
}

int ULC_ACData::Caculate(ULC_Balls *balls)
{
	int i, j;
	int dtIndex = 0;

	Init();

	if (balls == NULL){
		return -1;
	}

	for (i = 0; i < UL_RED_BALLS_COUNT; i++){
		redBalls[i] = balls->reds[i];
	}

	for (i = 0; i < UL_RED_BALLS_COUNT - 1; i++){
		for (j = i + 1; j < UL_RED_BALLS_COUNT; j++){
			dtDataOut[dtIndex++] = redBalls[j] - redBalls[i];
		}
	}

	dtIndex = 0;
	//Setup dtDataFinal(strip dumplicated data in dtDataOut)
	for (i = 0; i < DT_DATA_MAX_SIZE; i++){
		if (NumberExisted(dtDataFinal, i, dtDataOut[i])){
			continue;
		}

		dtDataFinal[dtIndex++] = dtDataOut[i];
	}

	dtDiff = dtIndex;
	ac = dtDiff - (UL_RED_BALLS_COUNT - 1);

	return 0;
}

ostream& operator<<(ostream &os, const ULC_ACData &acData)
{
	os << "--------------------AC---------------------" << endl;

	os << "AC: " << acData.ac << endl;
	os << "Red Numbers: ";

	for (int i = 0; i < UL_RED_BALLS_COUNT; i++){
		os << acData.redBalls[i] << " ";
	}

	os << endl << "Diffrent Deltas: " << acData.dtDiff << endl;
	os << "Deltas(No dumplicated data): ";

	for (int i = 0; i < DT_DATA_MAX_SIZE; i++){

		if (acData.dtDataFinal[i] == -1){
			break;
		}

		os << acData.dtDataFinal[i] << " ";
	}

	os << endl << "Deltas(Caculated result): ";

	for (int i = 0; i < DT_DATA_MAX_SIZE; i++){

		if (acData.dtDataOut[i] == -1){
			break;
		}

		os << acData.dtDataOut[i] << " ";
	}

	os << endl;

	return os;
}

//ULC_StandardDeviation
void ULC_StandardDeviation::Init()
{
	stdDeviation = average = 0.0f;
}

ULC_StandardDeviation::ULC_StandardDeviation()
{
	Init();
}

ULC_StandardDeviation::ULC_StandardDeviation(int *statData, int size)
{
	Caculate(statData, size);
}

int ULC_StandardDeviation::Caculate(int *statData, int size)
{
	double sumDt2 = 0.0f; 
	double dt;

	Init();

	if (statData == NULL){
		return -1;
	}

	for (int i = 0; i < size; i++){
		average += statData[i];
	}	

	average /= size;

	//Caculate standard deviation
	for (int i = 0; i < size; i++){
		dt = statData[i] - average;
		sumDt2 += dt * dt;
	}

	stdDeviation = sqrt(sumDt2 / size);
	
	return 0;
}

ostream& operator<<(ostream &os, const ULC_StandardDeviation &stdDev)
{
	os << "Standard deviation: " << stdDev.stdDeviation << " Average: " << stdDev.average << endl;
}
